#include "image.h"


Image::Image(){
	rows = 0;
	cols = 0;
	magicNumber = " ";
	maxVal = 0;
	imageArr = NULL;
}
//////////////////////////////////////////////////////////////////////////////////////////////

Image::Image(int Numcols, int Numrows, string mNumber, int maxValue){
	cols = Numcols;
	rows = Numrows;
	magicNumber = mNumber;
	maxVal = maxValue;

	imageArr = new Pixel* [rows];
	
	for(int i = 0; i < rows; i++)
		imageArr[i] = new Pixel [cols];

}
//////////////////////////////////////////////////////////////////////////////////////////////

Image::~Image(){
	for(int j = 0; j < rows; j++)
		delete [] imageArr[j];

	delete [] imageArr;
}
//////////////////////////////////////////////////////////////////////////////////////////////

Image::Image(const Image& arr){
	cols = arr.cols;
	rows = arr.rows;
	magicNumber = arr.magicNumber;
	maxVal = arr.maxVal;

	imageArr = new Pixel* [rows];
	
	for(int i = 0; i < rows; i++)
		imageArr[i] = new Pixel [cols];

	for(int a = 0; a < rows; a++)
		for(int b = 0; b < cols; b++)
			imageArr[a][b] = arr.imageArr[a][b];
}
//////////////////////////////////////////////////////////////////////////////////////////////

Image& Image::operator =(const Image &rhs){
	if(this != &rhs){
		for(int j = 0; j < rows; j++)
			delete [] imageArr[j];

		delete [] imageArr;

	cols = rhs.cols;
	rows = rhs.rows;
	magicNumber = rhs.magicNumber;
	maxVal = rhs.maxVal;

	imageArr = new Pixel* [rows];
	
	for(int i = 0; i < rows; i++)
		imageArr[i] = new Pixel [cols];

	for(int a= 0; a < rows; a++)
		for(int b= 0; b < cols; b++)
			imageArr[a][b] = rhs.imageArr[a][b];
			
	}
	return *this;
}
///////////////////////////////////////////////////////////////////////////////////////////////

bool Image :: operator==(const Image& rhs){
	if(rhs.imageArr[0][0].r == this->imageArr[0][0].r)
		return true;
	else
	    return false;
};
///////////////////****These are the friend function that act on the image****/////////////////

Image flippedArrayVertical(Image image){
	Image imageTemp(image.cols, image.rows,image.magicNumber, image.maxVal);


	for(int i=0; i< image.rows; i++)
		for(int j = 0; j < image.cols; j++)
			imageTemp.imageArr[i][j] = image.imageArr[image.rows - (i+1)][j];
		
	return imageTemp;
}
///////////////////////////////////////////////////////////////////////////////////////////////

Image flippedArrayHoriz(Image image){
	Image imageTemp(image.cols, image.rows, image.magicNumber, image.maxVal);

	for(int i = 0; i < image.rows; i++)
		for(int j = 0; j < image.cols; j++)
			imageTemp.imageArr[i][j] = image.imageArr[i][image.cols - (j+1)];

	return imageTemp;
}
///////////////////////////////////////////////////////////////////////////////////////////////

Image rotate270(Image image)
{
	Image imageTemp(image.rows, image.cols, image.magicNumber, image.maxVal);
	for(int i = 0; i < image.cols; i++)
	{	for(int j = 0; j <image.rows;j++)
		{
			imageTemp.imageArr[i][j] = image.imageArr[j][image.cols - (i+1)];

		}	
	}

	
	return imageTemp;
}
//////////////////////////////////////////////////////////////////////////////////////////////

Image rotate90(Image image)
{
	Image imageTemp(image.rows, image.cols, image.magicNumber, image.maxVal);
	for(int i = 0; i < image.cols; i++)
		for(int j = 0; j <image.rows; j++)
		{
			imageTemp.imageArr[i][j] = image.imageArr[image.rows-(j+1)][i];
		}

	return imageTemp;
}
//////////////////////////////////////////////////////////////////////////////////////////////

Image rotate180(Image image)
{
	Image imageTemp(image.cols, image.rows, image.magicNumber, image.maxVal);
	int k = 0;
	int p = 0;
	for(int j = image.rows - 1; j >= 0; j--){	
		for(int i = image.cols - 1; i >= 0; i--){
			imageTemp.imageArr[k][p] = image.imageArr[j][i]; 
			p++;
		}
		k++;
		p = 0;
	}
	
	

	return imageTemp;
}
/////////////////////////////////////////////////////////////////////////////////////////////

Image enlarge(Image image){
	int newWidth  = 2 * image.cols;
	int newHeight = 2 * image.rows;

	Image imageTemp(newWidth, newHeight, image.magicNumber, image.maxVal);
	
			    
	for(int i=0; i<image.rows; i++)
		for(int k=0;k <image.cols; k++) { 
			imageTemp.imageArr[2*i][2*k]= image.imageArr[i][k];
			imageTemp.imageArr[2*i][2*k+1]= image.imageArr[i][k];
			imageTemp.imageArr[2*i+1][2*k]= image.imageArr[i][k];
			imageTemp.imageArr[2*i+1][2*k+1]= image.imageArr[i][k];

	 }

	 return imageTemp;

}
///////////////////////////////////////////////////////////////////////////////////////////////

Image shrink(Image image){
	int newWidth  =  image.cols/2;
	int newHeight =  image.rows/2;

	Image imageTemp(newWidth, newHeight, image.magicNumber, image.maxVal);

	int i, j;
         for ( i=0; i < imageTemp.rows; i++)
			 for ( j=0; j < imageTemp.cols; j++)
             {
                 int average=0;
				 average += image.imageArr[2*i][2*j].r;
                 average += image.imageArr[2*i][2*j+1].r;
                 average += image.imageArr[2*i+1][2*j].r;
                 average += image.imageArr[2*i+1][2*j+1].r;
				 imageTemp.imageArr[i][j].r = average/4;
				 average=0;
                 average += image.imageArr[2*i][2*j].g;
                 average += image.imageArr[2*i][2*j+1].g;
                 average += image.imageArr[2*i+1][2*j].g;
                 average += image.imageArr[2*i+1][2*j+1].g;
				 imageTemp.imageArr[i][j].g = average/4;

				 average=0;
                 average += image.imageArr[2*i][2*j].b;
                 average += image.imageArr[2*i][2*j+1].b;
                 average += image.imageArr[2*i+1][2*j].b;
                 average += image.imageArr[2*i+1][2*j+1].b;
				 imageTemp.imageArr[i][j].b = average/4;
             }
	 return imageTemp;

}
/////////////////////////////////////////////////////////////////////////////////////////////

void Split(Image image, string name){
	
	string rname = name + ".r.pgm";
	string gname = name + ".g.pgm";
	string bname = name + ".b.pgm";
	
	ofstream outr(rname.c_str());
	ofstream outg(gname.c_str());
	ofstream outb(bname.c_str());
	
	
	outr<<"P2"<<endl<<image.cols<<" "<<image.rows<<endl<<image.maxVal<<endl;
	outg<<"P2"<<endl<<image.cols<<" "<<image.rows<<endl<<image.maxVal<<endl;
	outb<<"P2"<<endl<<image.cols<<" "<<image.rows<<endl<<image.maxVal<<endl;

	
	for(int r = 0; r < image.rows; r++)
		for(int c = 0; c < image.cols; c++){
			outr<<image.imageArr[r][c].r<<endl;
			outg<<image.imageArr[r][c].g<<endl;
			outb<<image.imageArr[r][c].b<<endl;
		}
}  
//////////////////////////////////////////////////////////////////////////////////////////////

Image changeBrightness(Image image){
		float change;
		int resp;

		cout<<"1. Increase Brightness"<<endl;
		cout<<"2. Decrease Brightness"<<endl;
	    cout<<"Option: ";
		cin>>resp;
		cout<<endl;
			while(resp < 1 || resp > 2)
			{
				cout<<"Please enter either 1 or 2."<<endl;
				cin>>resp;
			}
		if(resp == 1){
			cout<<"Please enter the amount you want to increase the brightness 1 - 100: ";
			cin>>change;
			for(int i = 0; i < image.rows; i++)
				for(int j = 0; j < image.cols; j++){
					image.imageArr[i][j].r += change;
					if(image.imageArr[i][j].r > 255)
						image.imageArr[i][j].r = 255;
					image.imageArr[i][j].g += change;
					if(image.imageArr[i][j].g > 255)
						image.imageArr[i][j].g = 255;
					image.imageArr[i][j].b += change;
					if(image.imageArr[i][j].b > 255)
						image.imageArr[i][j].b = 255;
				}
		}
		else{
			cout<<"Please enter the amount you want to decrease the brightness 1 - 100: ";
			cin>>change;

			for(int i = 0; i < image.rows; i++)
				for(int j = 0; j < image.cols; j++){
					image.imageArr[i][j].r -= change;
					if(image.imageArr[i][j].r < 0)
						image.imageArr[i][j].r = 0;

					image.imageArr[i][j].g -= change;
					if(image.imageArr[i][j].g < 0)
						image.imageArr[i][j].g = 0;

					image.imageArr[i][j].b -= change;
					if(image.imageArr[i][j].b < 0)
						image.imageArr[i][j].b = 0;
				}
		}
		return image;

}
//////////////////////////////////////////////////////////////////////////////////////////////

Image changeContrast(Image image){
    
	  float change;
	  int resp;

		cout<<"1. Increase Contrast"<<endl;
		cout<<"2. Decrease Contrast"<<endl;
	    cout<<"Option: ";
		cin>>resp;
		cout<<endl;
			while(resp < 1 || resp > 2)
			{
				cout<<"Please enter either 1 or 2."<<endl;
				cin>>resp;
			}
		if(resp == 1){
		cout<<"Please enter the amount you want to increase the contrast 1 - 100: ";
		cin>>change;
		
		for (int i=0; i < image.rows; i++)
			for(int j=0; j < image.cols; j++){
				image.imageArr[i][j].r *= change;
					if(image.imageArr[i][j].r > 255)
						image.imageArr[i][j].r = 255;

					image.imageArr[i][j].g *= change;
					if(image.imageArr[i][j].g > 255)
						image.imageArr[i][j].g = 255;

					image.imageArr[i][j].b *= change;
					if(image.imageArr[i][j].b > 255)
						image.imageArr[i][j].b = 255;
			}
			
		}

	
     
      return image;
      
}  
//////////////////////////////////////////////////////////////////////////////////////////////

Image alphaBlend (Image image)
{

	//  Ask the user for a new image to blend the current image with and load it into a new array
	//  Some of this I copied and pasted from main like loading the array and everything
	//  I just changed it from image to imageTemp

	cout<<"Please enter the name of the image that you would like to blend with the current image:  ";
	string name;
	cin>>name;



	ifstream infile(name.c_str());
	 
	if(!infile){
		cout<<"File Not Found!"<<endl;
		return image;
	}

	string magicNumber;
	infile>>magicNumber;
	
	int numRows, numCols, maxValue;
		
	infile>>numCols>>numRows>>maxValue;
		
	Image imageTemp(numCols , numRows, magicNumber, maxValue);

	Pixel temp;

	for(int i =0; i < numRows; i++){
			for(int j =0; j < numCols; j++){
				infile>>temp.r;
				infile>>temp.g;
				infile>>temp.b;
				imageTemp.setPixel(temp, i ,j);
			}
	}

	/*************************************************************/
	//  Get a number between 0 and 1 for percentage of original images to blend together
	//  
	
	cout<<"\nPlease enter a number between 0 and 1 for the amount of blending desired: "; 
	float num1, num2;
	cin>>num1;
	
	while (num1 >0.9 || num1 < 0.1)
	{
		cout<<"\nInvalid response.  Please enter a number between 0 and 1: ";
		cin>>num1;
		cout<<endl;
	}

	num2 = 1.0 - num1;

	/***********************************************************/
	//  Multiply each part of the image arrays with their percentage of blending:

	for (int i = 0; i < imageTemp.rows; i ++){
		for (int j = 0; j < imageTemp.cols; j++){
			imageTemp.imageArr[i][j].r = imageTemp.imageArr[i][j].r * num2;
			imageTemp.imageArr[i][j].g = imageTemp.imageArr[i][j].g * num2;
			imageTemp.imageArr[i][j].b = imageTemp.imageArr[i][j].b * num2;
			imageTemp.imageArr[i][j].r = (int)imageTemp.imageArr[i][j].r;
			imageTemp.imageArr[i][j].g = (int)imageTemp.imageArr[i][j].g;
			imageTemp.imageArr[i][j].b = (int)imageTemp.imageArr[i][j].b;
		}
	}
	
	for (int i = 0; i < image.rows; i ++){
		for (int j = 0; j < image.cols; j++){
			image.imageArr[i][j].r = image.imageArr[i][j].r * num1;
			image.imageArr[i][j].g = image.imageArr[i][j].g * num1;
			image.imageArr[i][j].b = image.imageArr[i][j].b * num1;
			image.imageArr[i][j].r = (int)image.imageArr[i][j].r;
			image.imageArr[i][j].g = (int)image.imageArr[i][j].g;
			image.imageArr[i][j].b = (int)image.imageArr[i][j].b;

		}
	}

	

	/***********************************************************/
	//  Blend the images together
	//  The minRows part I added last.  I kept getting an error while it was executing
	//  until I added that part, then it worked

	int minRows, minCols;

	if(image.rows < imageTemp.rows)
		minRows = image.rows;
	else
		minRows = imageTemp.rows;

	if(image.cols< imageTemp.cols)
		minCols = image.cols;
	else
		minCols = imageTemp.cols;

	for ( int i = 0; i < minRows; i ++){
		for (int j = 0; j < minCols; j++){
			image.imageArr[i][j].r = imageTemp.imageArr[i][j].r + image.imageArr[i][j].r;
			image.imageArr[i][j].g = imageTemp.imageArr[i][j].g + image.imageArr[i][j].g;
			image.imageArr[i][j].b = imageTemp.imageArr[i][j].b + image.imageArr[i][j].b;
		}
	}

	return image;
}
/////////////////////////////////////////////////////////////////////////////////////////

void processColor(string name){
	cout<<"Welcome to the CS232 Color Image Editor!"<<endl<<endl;
     
  

//makeing the image array of the infile///////////////////////////////////////////////////////

	ifstream infile(name.c_str());

	if(!infile){
		cout<<"File Not Found! Program will now close."<<endl;
		cout<<"Please Exit The Program"<<endl;
	}

	string magicNumber;
	infile>>magicNumber;
	
	int numRows, numCols, maxValue;
		
	infile>>numCols>>numRows>>maxValue;
		
	Image image(numCols , numRows, magicNumber, maxValue);

	Pixel temp;

	for(int i =0; i < numRows; i++){
			for(int j =0; j < numCols; j++){
				infile>>temp.r;
				infile>>temp.g;
				infile>>temp.b;
				image.setPixel(temp, i, j);
			}
	}

//main menu/////////////////////////////////////////////////////////////////////////////////
int resp = 0;
string save;
Image original = image;//this is for option 7
while(resp != 8){    
	
	int option = 0;

	cout<<"1. Flip the image"<<endl;
	cout<<"2. Rotate the image" <<endl;
	cout<<"3. Shrink or Enlarge the image"<<endl;
	cout<<"4. Modify the brightness/contrast of the image"<<endl;
	cout<<"5. Alpha Blend the image"<<endl;
	cout<<"6. Split the image into 3 greyscal images"<<endl;
	cout<<"7. Return image to original look"<<endl;
	cout<<"8. Exit"<<endl;
	cout<<"Please enter option here: ";
	cin>>resp;
	

	while(resp > 8 || resp < 1){
		cout<<"Invailid choice. Please Choose an Option 1 - 8: ";
		cin>>resp;
		system("cls");
	}
	system("cls");

//this is for when you want to the flip the image.
	if(resp == 1){
		option = 0;
		cout<<"1.  Flip Horiztonally?"<<endl;
		cout<<"2.  Flip Vertically?"<<endl;
		
		cout<<"Option: ";
		cin>>option;
			while(option < 1 || option > 2)
			{
				cout<<"Please enter either 1 or 2."<<endl;
				cin>>option;
			}
		if(option == 1)
			  image = flippedArrayHoriz(image);
		else
			  image = flippedArrayVertical(image);

		cout<<"The process is now complete."<<endl;
		system("pause");
		system("cls");
	}//end response 1

	else if(resp == 2)
	{	
		option = 0;
		cout<<"1. Rotate by 90?"<<endl;
		cout<<"2. Rotate by 180?"<<endl;
		cout<<"3. Rotate by 270?"<<endl;
		cout<<"Option : "<<endl;
		cin>>option;
		
		while(option < 1 || option > 3)
		{
			cout<<"Please select a number between 1 and 3: ";
			cin>>option;
		}

		if(option == 1)
		{
			image = rotate90(image);
		}
		else if(option == 2)
		{
			image = rotate180(image);
		}
		else
			image = rotate270(image);

		cout<<"The process is now complete."<<endl;
		system("pause");
		system("cls");
	}//end response 2

	else if(resp == 3){
		option = 0;
		cout<<"1. Enlarge?"<<endl;
		cout<<"2. Shrink?"<<endl;
		
		cout<<"Option: ";
		cin>>option;
			while(option < 1 || option > 2)
			{
				cout<<"Please enter either 1 or 2."<<endl;
				cin>>option;
			}
		if(option == 1)
			  image = enlarge(image);
		else
			  image = shrink(image);

		cout<<"The process is now complete."<<endl;
		system("pause");
		system("cls");
	}//end response 3

	else if(resp == 4){
		cout<<"1. Change Brightness"<<endl;
		cout<<"2. Change Contrast"<<endl;
	    cout<<"Option: ";
		cin>>option;
			while(option < 1 || option > 2)
			{
				cout<<"Please enter either 1 or 2."<<endl;
				cin>>option;
			}
		if(option == 1)
			  image = changeBrightness(image);
		else
			  image = changeContrast(image);

		cout<<"The process is now complete."<<endl;
		system("pause");
		system("cls");
	}//end response 4

	else if(resp == 5){
		image = alphaBlend(image);
		if( image == original)
			cout<<"The process could not be completed!"<<endl;
		else
			cout<<"The process is now complete."<<endl;

		system("pause");
		system("cls");
	}//end response 5

	else if(resp == 6){		
			Split(image, name);
			cout<<"The process is now complete."<<endl;
			system("pause");
			system("cls");
		
		
	}//end response 6

	else if(resp == 7){
		image = original;
		cout<<"The process is now complete."<<endl;
		system("pause");
		system("cls");
	}//end response 7

	else {
		cout<<"Thanks for using the CS232 Image Editor."<<endl;
	}
	

	if(resp !=8 && resp != 6){

		cout<<"Would you like to save! Please enter yes or no: ";
		cin>>save;
		cout<<endl;

		if(save == "yes"){

			string modName = "mod" + name ;
			ofstream outfile(modName.c_str());
			

			outfile<<magicNumber<<endl;
			outfile<<image.getCols()<<" "<<image.getRows()<<endl;
			outfile<<maxValue<<endl;
				
			for(int i =0; i < image.getRows(); i++){
				for(int j =0; j < image.getCols(); j++){
					outfile<<image.getPixel(i,j).r<<" ";
					outfile<<image.getPixel(i,j).g<<" ";
					outfile<<image.getPixel(i,j).b<<" ";
					outfile<<endl;
				}
			}
			outfile.close();
			cout<<"Save now complete."<<endl;
			system("pause");
			system("cls");
		}
	}
	
}
	infile.close();

}
///////////////////////////////////////////////////////////////////////////////////////
		
